package com.leinao.config.init;

import cn.hutool.core.collection.CollectionUtil;
import com.leinao.core.DevicePool;
import com.leinao.core.DevicePointPool;
import com.leinao.core.FailDeviceIdPool;
import com.leinao.core.RegularPointConverter;
import com.leinao.domain.*;
import com.leinao.domain.param.DeviceDataQueryParam;
import com.leinao.service.impl.*;
import com.leinao.utils.DateUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * description
 *
 * @author zhong.wang
 * @date 2025/1/13
 */
@Component
@Order(Integer.MAX_VALUE)
public class InitDataBase {

    @Resource
    private MysqlFromDeviceService fromDeviceService;
    @Resource
    private MysqlToDeviceService toDeviceService;

    @Resource
    private MysqlToDeviceModelService deviceModelService;

    @Resource
    private MySqlFromRegularPointInfoService fromRegularPointInfoService;

    @Resource
    private MysqlToRegularPointInfoService toRegularPointInfoService;

    @Resource
    private MysqlFromDevicePointService fromDevicePointService;

    @Resource
    private MysqlToDevicePointService toDevicePointService;

    @Resource
    private TdengingToService toTdengineService;
    @Resource
    private TdengineFromService fromTdengineService;


    @PostConstruct
    public void init(){

         initTdengine();

        // init 设备对应关系
        this.initDevicePool();

        // init 固定测点对应关系
        this.initRegularPointPool();

        this.initDevicePointPool();
        DevicePool instance = DevicePool.getInstance();
        System.out.println(instance);

        for (Long deviceId : DevicePool.getInstance().getDeviceIds()) {
            System.out.println("deviceId " + deviceId);
            this.insertData(deviceId);
        }
//        List<Long> list = Arrays.asList( 456L, 457L, 458L, 459L, 460L, 461L, 462L, 463L, 464L, 465L);
//        for (Long aLong : list) {
//            this.insertData(aLong);
//        }
//            this.insertData(aLong);
//        }


    }

    /**
     * 初始化数据库
     */
    private void initTdengine() {
        List<SysDeviceModel> deviceModels = deviceModelService.getDeviceModelList();
        if(CollectionUtil.isNotEmpty(deviceModels)){
            deviceModels.forEach(model->{
                toTdengineService.deleteTable("device_model_"+model.getId());
                toTdengineService.createTable("device_model_"+model.getId());
            });
        }
    }


    /**
     * 初始化设备对应关系
     */
    private void initDevicePool() {
        List<SysDevice> fromDeviceList = fromDeviceService.getDeviceList();
        List<SysDevice> toDeviceList = toDeviceService.getDeviceList();

        if(CollectionUtil.isNotEmpty(fromDeviceList) && CollectionUtil.isNotEmpty(toDeviceList)){
            Map<Long, List<SysDevice>> fromDeviceMap = fromDeviceList.stream().collect(Collectors.groupingBy(SysDevice::getDeviceTypeId));
            for (SysDevice sysDevice : toDeviceList) {
                if(fromDeviceMap.containsKey(sysDevice.getDeviceTypeId())){
                    List<Long> fromDeviceIds = fromDeviceMap.get(sysDevice.getDeviceTypeId()).stream().map(SysDevice::getId).collect(Collectors.toList());
                    DevicePool.getInstance().addRelation(sysDevice.getId(),fromDeviceIds);
                }
            }

            Map<Long,SysDevice> toDeviceMap = toDeviceList.stream().collect(Collectors.toMap(SysDevice::getId,Function.identity()));
            for (Long deviceId : toDeviceMap.keySet()) {
                DevicePool.getInstance().registerToDevice(deviceId,toDeviceMap.get(deviceId));
            }
        }

    }

    /**
     * 初始化固定测点池
     */
    private void initRegularPointPool(){

        // init 固定测点对应关系
        List<SysRegularPointInfo> fromRegularPointInfos = fromRegularPointInfoService.getRegularPointInfoList();

        List<SysRegularPointInfo> toRegularPointInfos = toRegularPointInfoService.getRegularPointInfoList();
        if(CollectionUtil.isNotEmpty(fromRegularPointInfos) && CollectionUtil.isNotEmpty(toRegularPointInfos)){
            Map<String, List<SysRegularPointInfo>> toRegularPointInfoMap =
                    toRegularPointInfos.stream()
                            .collect(Collectors.groupingBy(
                                    info -> info.getDeviceType() + ":" + info.getRegularPointName()
                            ));

            for (SysRegularPointInfo fromRegularPointInfo : fromRegularPointInfos) {
                String key = fromRegularPointInfo.getDeviceType() + ":" + fromRegularPointInfo.getRegularPointName();
                if(toRegularPointInfoMap.containsKey(key)){
                    RegularPointConverter.getInstance().addRelation(fromRegularPointInfo.getId(),toRegularPointInfoMap.get(key).stream().map(SysRegularPointInfo::getId).collect(Collectors.toList()));
                }
            }
        }
    }

    /**
     * 初始化测点池
     */
    private void initDevicePointPool() {
        DevicePointPool instance = DevicePointPool.getInstance();
        List<SysDevicePoint> fromPointList = fromDevicePointService.getDevicePointList();

        if(CollectionUtil.isNotEmpty(fromPointList)){
            Map<Long, List<SysDevicePoint>> devicePointMap = fromPointList.stream().collect(Collectors.groupingBy(SysDevicePoint::getDeviceId));
            for (Long deviceId : devicePointMap.keySet()) {
                if(Objects.nonNull(deviceId)){
                    DevicePointPool.getInstance().registerFromDevicePoint(deviceId,devicePointMap.get(deviceId));
                }
            }
        }

        List<SysDevicePoint> toPointList = toDevicePointService.getDevicePointList();
        if(CollectionUtil.isNotEmpty(toPointList)){
            Map<Long, List<SysDevicePoint>> devicePointMap = toPointList.stream().collect(Collectors.groupingBy(SysDevicePoint::getDeviceId));
            for (Long deviceId : devicePointMap.keySet()) {
                if(Objects.nonNull(deviceId)){
                    DevicePointPool.getInstance().registerToDevicePoint(deviceId,devicePointMap.get(deviceId));
                }
            }
        }
    }


    private void insertData(Long toDeviceId){
        List<DeviceData> deviceDataList = getDeviceDataList(toDeviceId);
        if (CollectionUtil.isEmpty(deviceDataList)) {
            FailDeviceIdPool.getInstance().addRelation(toDeviceId);
            return; // 如果没有数据，则直接返回，不再执行后续代码
        }

        // 分页插入数据
        paginateAndInsert(deviceDataList, 2000);
    }

    /**
     * 分页处理并插入数据
     *
     * @param dataList 要插入的数据列表
     * @param pageSize 每页大小
     */
    private void paginateAndInsert(List<DeviceData> dataList, int pageSize) {
        System.out.println("insert count:" + dataList.size());
        int totalSize = dataList.size();
        int pages = (int) Math.ceil((double) totalSize / pageSize);

        for (int i = 0; i < pages; i++) {
            int fromIndex = i * pageSize;
            int toIndex = Math.min(fromIndex + pageSize, totalSize);

            List<DeviceData> pageData = dataList.subList(fromIndex, toIndex);
            toTdengineService.insertDeviceData(pageData);
        }
    }

    private List<DeviceData> getDeviceDataList(Long toDeviceId){
        Long fromDeviceId = DevicePool.getInstance().getRandomDeviceId(toDeviceId);
        //System.out.println(fromDeviceId);
        fromDeviceId = 504L;
        List<SysDevicePoint> toDevicePointList = DevicePointPool.getInstance().getPointListTo(toDeviceId);
        if(CollectionUtil.isEmpty(toDevicePointList)){
            return new ArrayList<>();
        }
        List<SysDevicePoint> fromDevicePointList = DevicePointPool.getInstance().getPointListFrom(fromDeviceId);
        if(CollectionUtil.isEmpty(fromDevicePointList)){
            List<DeviceData> deviceDataList = getDeviceDataList(toDeviceId);
            return deviceDataList;
        }
        List<DeviceData> result = new ArrayList<>();
        Map<Long, List<Long>> pointRelation = getPointRelation(toDevicePointList, fromDevicePointList);
        DeviceDataQueryParam queryParam = new DeviceDataQueryParam();
        queryParam.setDeviceId(fromDeviceId);
        queryParam.setTableName("device_"+fromDeviceId);
        queryParam.setStartTime("2024-12-01 00:00:00");
        queryParam.setEndTime("2024-12-11 00:00:00");
        List<DeviceData> deviceDataList = fromTdengineService.getListByTs(queryParam);
        if(CollectionUtil.isEmpty(deviceDataList)){
            getDeviceDataList(toDeviceId);
        }else{
            for (DeviceData deviceData : deviceDataList) {
                if(pointRelation.containsKey(deviceData.getPointId())){
                    List<Long> pointIdList = pointRelation.get(deviceData.getPointId());
                    for (Long pointId : pointIdList) {
                        DeviceData clone = (DeviceData) deviceData.clone();
                        clone.setTsString(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,deviceData.getTs()));
                        clone.setPointId(pointId);
                        clone.setDeviceId(toDeviceId);
                        clone.setStationId(DevicePool.getInstance().getById(toDeviceId).getStationId());
                        clone.setStationAreaId(DevicePool.getInstance().getById(toDeviceId).getStationAreaId());
                        clone.setChildTableName("device_"+DevicePool.getInstance().getById(toDeviceId).getId());
                        clone.setSTableName("device_model_"+DevicePool.getInstance().getById(toDeviceId).getDeviceModelId());
                        result.add(clone);
                    }
                }
            }
            if(CollectionUtil.isEmpty(result)){
                return new ArrayList<>();
            }
        }
        return result;
    }

    public Map<Long,List<Long>> getPointRelation(List<SysDevicePoint> toDevicePointList,List<SysDevicePoint> fromDevicePointList){
        RegularPointConverter regularPointConverter = RegularPointConverter.getInstance();

        Map<Long,List<Long>> result = new HashMap<>();
        Map<Long, SysDevicePoint> toDevicePointMap = toDevicePointList.stream()
                .collect(Collectors.toMap(
                        SysDevicePoint::getRegularPointId,
                        Function.identity(),
                        (existing, replacement) -> existing // 在发生冲突时保留现有的（即第一个）元素
                ));
        for (SysDevicePoint sysDevicePoint : fromDevicePointList) {
            Long fromRegularPointId = sysDevicePoint.getRegularPointId();
            if(RegularPointConverter.getInstance().hasId(fromRegularPointId)){
                List<Long> toRegularPointId = RegularPointConverter.getInstance().getByKey(fromRegularPointId);
                for (Long aLong : toRegularPointId) {
                    if(toDevicePointMap.containsKey(aLong)){
                        result.computeIfAbsent(sysDevicePoint.getId(), k -> new ArrayList<>())
                                .add(toDevicePointMap.get(aLong).getId());
                    }
                }
            }
        }

        return result;
    }



}
